﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;

namespace Gencode.VECore.VectorShape
{
	public class VECLine : VECShape
	{
        /// <summary>
        /// Serializer object description
        /// </summary>
        private const string serLineStart = "LineStart";
        private const string serLineEnd = "LineEnd";

        public VECLine()
            : this(0, 0, 1, 0)
        {
        }

		public VECLine(double x1, double y1, double x2, double y2)
			: base()
		{
			_definingGeometry = new LineGeometry();
			_definingGeometry.StartPoint = new Point(x1, y1);
			_definingGeometry.EndPoint = new Point(x2, y2);

			this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MouseLeftUp);
		}

        /// <summary>
        /// Clone this instance
        /// </summary>
        public override VECShape Clone()
        {
            VECLine drawLine = new VECLine();
            drawLine.StartPoint = this.StartPoint;
            drawLine.EndPoint = this.EndPoint;

            CopyShapeProperies(drawLine);
            return drawLine;
        }

		protected override void OnRender(DrawingContext drawingContext)
		{
			base.OnRender(drawingContext);

			if (Selected)
			{
				Pen p = new Pen(Brushes.Blue, 1);
				drawingContext.DrawEllipse(Brushes.LightBlue, p, _definingGeometry.StartPoint, 2.5, 2.5);
				drawingContext.DrawEllipse(Brushes.LightBlue, p, _definingGeometry.EndPoint, 2.5, 2.5);
			}
		}

		public double Distance(Point point1, Point point2)
		{
			//C^2=a^2+b^2
			double xdist = 0.0;
			if (point1.X > point2.X)
				xdist = point1.X - point2.X;
			else
				xdist = point2.X - point1.X;

			double ydist = 0.0;
			if (point1.Y > point2.Y)
				ydist = point1.Y - point2.Y;
			else
				ydist = point2.Y - point1.Y;

			//C^2=a^2+b^2
			return Math.Sqrt((ydist * ydist) + (xdist * xdist));
		}

		private void MouseLeftUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
		{
            if (CanvasDocument.SelectedToolType == Gencode.VECore.ToolType.SelectionTool)
			{
				if (!Selected)
				{
					Selected = true;
				}
			}
		}

		LineGeometry _definingGeometry;
		protected override Geometry DefiningGeometry
		{
			get 
			{
				if (_definingGeometry == null)
					_definingGeometry = new LineGeometry();

				return _definingGeometry;
			}
		}

		public Point StartPoint
		{
			get
			{
				return _definingGeometry.StartPoint;
			}
			set
			{
				_definingGeometry.StartPoint = value;
                ////this.InvalidateVisual();
			}
		}

		public Point EndPoint
		{
			get
			{
				return _definingGeometry.EndPoint;
			}
			set
			{
				_definingGeometry.EndPoint = value;
                this.InvalidateVisual();
			}
		}




		public override int HandleCount
		{
			get
			{
				return 2;
			}
		}

		/// <summary>
		/// Get handle point by 1-based number
		/// </summary>
		/// <param name="handleNumber"></param>
		/// <returns></returns>
		public override Point GetHandle(int handleNumber)
		{
			if (handleNumber == 1)
				return StartPoint;
			else
				return EndPoint;
		}

		/// <summary>
		/// Hit test.
		/// Return value: -1 - no hit
		///                0 - hit anywhere
		///                > 1 - handle number
		/// </summary>
		/// <param name="point"></param>
		/// <returns></returns>
		public override int HitTest(Point point)
		{
			if (Selected)
			{
				for (int i = 1; i <= HandleCount; i++)
				{
					if (GetHandleRectangle(i).Contains(point))
						return i;
				}
			}

			if (PointInObject(point))
				return 0;

			return -1;
		}

        protected override bool PointInObject(Point point)
        {
            return _definingGeometry.StrokeContains(new Pen(this.Stroke, this.StrokeThickness), point);
        }

		public override bool IntersectsWith(Rect rectangle)
        {
            RectangleGeometry rectgeo = new RectangleGeometry(rectangle,0,0);
            IntersectionDetail det = _definingGeometry.StrokeContainsWithDetail(new Pen(this.Stroke, this.StrokeThickness), rectgeo);

            if (det == IntersectionDetail.FullyContains || det == IntersectionDetail.FullyInside || det == IntersectionDetail.Intersects)
                return true;

            return false;
        }

		public override System.Windows.Input.Cursor GetHandleCursor(int handleNumber)
		{
			switch (handleNumber)
			{
				case 1:
				case 2:
					return System.Windows.Input.Cursors.SizeAll;
				default:
					return System.Windows.Input.Cursors.Arrow;
			}
		}

		public override void MoveHandle(Point point, int handleNumber)
		{
			if (handleNumber == 1)
				StartPoint = point;
			else
				EndPoint = point;

			this.InvalidateVisual();

            CallChangedHandler();
		}

		public override void Move(double deltaX, double deltaY)
		{
			StartPoint = new Point(StartPoint.X + deltaX, StartPoint.Y + deltaY);
			EndPoint = new Point(EndPoint.X + deltaX, EndPoint.Y + deltaY);

            CallMovedHandler();
		}

        public override void SaveToStream(System.Runtime.Serialization.SerializationInfo info, int orderNumber)
        {
            info.AddValue(
                String.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}{1}",
                serLineStart, orderNumber),
                StartPoint);

            info.AddValue(
                String.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}{1}",
                serLineEnd, orderNumber),
                EndPoint);

            base.SaveToStream(info, orderNumber);
        }

        public override void LoadFromStream(System.Runtime.Serialization.SerializationInfo info, int orderNumber)
        {
            StartPoint = (Point)info.GetValue(
                String.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}{1}",
                serLineStart, orderNumber),
                typeof(Point));

            EndPoint = (Point)info.GetValue(
                String.Format(System.Globalization.CultureInfo.InvariantCulture,
                "{0}{1}",
                serLineEnd, orderNumber),
                typeof(Point));

            base.LoadFromStream(info, orderNumber);
        }
	}
}
